/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.csvgenerator.engine.value;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author mjocic
 */
public class ValueProducerLookup {

    private static ValueProducerLookup instance;
    private Map<Long, ValueProducer> valueProducers;

    private ValueProducerLookup() {
        valueProducers = new HashMap<Long, ValueProducer>();
    }

    public static ValueProducerLookup getInstance() {
        if (instance == null) {
            instance = new ValueProducerLookup();
        }
        return instance;
    }

    public String getFullClassName(String className) throws ClassNotFoundException {
        //System.out.println("Calculating full class name for class " + className);
        if (className.endsWith("ValueGenerator")) {
            return "com.csvgenerator.engine.vg." + className;
        } else if (className.endsWith("ValueCombinator")) {
            return "com.csvgenerator.engine.vc." + className;
        } else if (className.endsWith("ValueModifier")) {
            return "com.csvgenerator.engine.vm." + className;
        } else if (className.endsWith("ValueReferencer")) {
            return "com.csvgenerator.engine.vr." + className;
        } else {
            throw new ClassNotFoundException(className);
        }
    }

    public void addValueProducer(Long id, ValueProducer vp) throws ValueProducerWithIdExistsException {
        if (!valueProducers.containsKey(id)) {
            valueProducers.put(id, vp);
            return;
        }
        throw new ValueProducerWithIdExistsException(id);
    }

    public boolean valueProducerExists(Long id) {
        return valueProducers.containsKey(id);
    }

    public ValueProducer getValueProducer(Long id) throws ValueProducerDoesntExistException {
        if (valueProducers.containsKey(id)) {
            return valueProducers.get(id);
        }
        throw new ValueProducerDoesntExistException(id);
    }

    /**
     * This method creates new instance of specific value producer class
     * based on input parameters.
     * @param fullClassName Full class name of value producer class
     * @return New instance of <code>Value Producer</code>
     */
    public ValueProducer createValueProducer(String fullClassName) {
        //System.out.println("Performing lookup for Class: " + fullClassName);
        ValueProducer vp = null;
        Class cl = null;
        Object obj = null;
        try {
            cl = Class.forName(fullClassName);
            obj = cl.newInstance();
            if (obj instanceof ValueProducer) {
                vp = (ValueProducer) obj;
            }
        } catch (InstantiationException ex) {
            System.out.println(ex);
        } catch (IllegalAccessException ex) {
            System.out.println(ex);
        } catch (IllegalArgumentException ex) {
            System.out.println(ex);
        } catch (SecurityException ex) {
            System.out.println(ex);
        } catch (ClassNotFoundException ex) {
            System.out.println(ex);
        }
        return vp;
    }

    /**
     * This method creates new instance of specific value producer class
     * based on input parameters.
     * @param fullClassName Full class name of value producer class
     * @return New instance of <code>Value Producer</code>
     */
    public Class getClassForFullName(String fullClassName) {
        //System.out.println("Performing lookup for Class: " + fullClassName);

        Class cl = null;

        try {
            cl = Class.forName(fullClassName);
        } catch (IllegalArgumentException ex) {
            System.out.println(ex);
        } catch (SecurityException ex) {
            System.out.println(ex);
        } catch (ClassNotFoundException ex) {
            System.out.println(ex);
        }
        return cl;
    }

    public List<ValueProducer> getValueProducersList() {
        List<ValueProducer> sortedList = new ArrayList<ValueProducer>();

        for (ValueProducer vp : valueProducers.values()) {
            if (vp.getId() < 0) {
                continue;
            }

            if (sortedList.isEmpty()) {
                sortedList.add(vp);
            } else {
                for (ValueProducer svp : sortedList) {
                    if (vp.getId() < svp.getId()) {
                        sortedList.add(sortedList.indexOf(svp), vp);
                        break;
                    }
                }
                if (!sortedList.contains(vp)) {
                    sortedList.add(vp);
                }
            }            
        }
        return sortedList;
    }

    /**
     * Find minimal id over all ValueProducers in generator
     * @return minId minimum id over all ValueProducers
     */
    public Long getMinId() {
        Long minId = Long.MAX_VALUE;
        for (Long key : valueProducers.keySet()) {
            if (key < minId) {
                minId = key;
            }
        }
        if (minId >= 0) {
            minId = new Long(-1);
        }
        return minId;
    }
}
